﻿using System;
using Web.Core.Extensions;
using System.Web.WebPages;
using Ayatta.Contract.Domain;
using System.Collections.Specialized;

namespace Web.Core.OnlinePays
{
    /// <summary>
    /// 银联支付
    /// </summary>
    internal sealed class ChinaPay : OnlinePay
    {
        private static string CuryId
        {
            get { return "156"; }
        }

        private static string Version
        {
            get { return "20070129"; }
        }

        private static string SuccessStatus
        {
            get { return "1001"; }
        }

        /// <summary>
        /// 银联支付
        /// </summary>
        /// <param name="platform"></param>
        public ChinaPay(PaymentPlatform platform): base(platform)
        {

        }

        /// <summary>
        /// 生成支付请求Url
        /// </summary>
        /// <returns></returns>
        public override string GetPayUrl(AccountPayment payment)
        {
            var param = new NameValueCollection();

            const string transType = "0001";
            var no = payment.Id;//系统订单号
            var payNo = payment.PayNo;//支付平台订单号
            var amount = GetAmount(payment.Amount * 100);
            var dateTime = GetDateTime(payment.CreatedOn);
            

            var plain = Platform.MerchantId + payNo + amount + CuryId + dateTime + transType + no;

            param.Add("MerId", Platform.MerchantId);
            param.Add("OrdId", payNo);
            param.Add("TransAmt", amount);
            param.Add("CuryId", CuryId);
            param.Add("TransDate", dateTime);
            param.Add("TransType", transType);
            param.Add("Version", Version);
            param.Add("BgRetUrl", Platform.NotifyUrl);
            param.Add("PageRetUrl", Platform.CallbackUrl);
            param.Add("GateId", payment.Gateway);
            param.Add("Priv1", no);//支付平台原样返回

            param.Add("ChkValue", CreateSign(plain));

            return Platform.GatewayUrl + param.ToQueryString(true,true,true);
        }

        /// <summary>
        /// 处理支付平台通知
        /// </summary>
        /// <param name="nv">第三方支付平台通知参数</param>
        /// <returns></returns>
        public override MagicKit<Notification> NotifyHandler(NameValueCollection nv)
        {
            var notification = new Notification(Platform.Id);
            var result = new MagicKit<Notification> { Data = notification };

            var merId = nv["MerId"]; //商户号
            var no = nv["Priv1"];//系统订单号
            var payNo = nv["OrderNo"]; //支付平台订单号
            var amount = nv["Amount"]; //订单金额
            var curyId = nv["CurrencyCode"]; //货币代码
            var payTime = nv["TransDate"]; //订单日期
            var transType = nv["TransType"]; //交易类型
            var status = nv["status"];
            var signature = nv["checkvalue"]; //签名数据 

            result.Data.No = no;
            result.Data.PayNo = payNo;
            result.Data.Amount = amount.AsInt(0) / 100M;
            result.Data.ExternalNo = string.Empty;
            result.Data.PayTime = DateTime.Now;
            result.Data.Signature = signature;

            var netPay = new NetPay();
            var flag = netPay.buildKey(Platform.MerchantId, 0, Platform.PublicKey);
            if (flag)
            {
                flag = netPay.PublicKeyFlag && netPay.verifyTransResponse(merId, payNo, amount, curyId, payTime, transType, status, signature);
            }
            if (flag && (status == SuccessStatus))
            {
                notification.Status = true;
                result.Status = OnNotified(notification);
            }
            else
            {
                result.Message = "验证签名失败";
            }
            return result;
        }

        /// <summary>
        /// 生成签名
        /// </summary>
        /// <param name="plain">待签名参数</param>
        /// <returns></returns>
        private string CreateSign(string plain)
        {
            var netPay = new NetPay();
            var flag = netPay.buildKey(Platform.MerchantId, 0, Platform.PrivateKey);
            string sign = null;
            if (flag)
            {
                if (netPay.PrivateKeyFlag)
                {
                    sign = netPay.Sign(plain);
                }
            }
            return sign;
        }

        /// <summary>
        /// 验证签名
        /// </summary>
        /// <param name="plain">待验证签名参数</param>
        /// <param name="sign">签名</param>
        /// <returns></returns>
        private bool VerifySign(string plain, string sign)
        {
            var netPay = new NetPay();
            var flag = netPay.buildKey(Platform.MerchantId, 0, Platform.PublicKey);
            if (flag)
            {
                flag = netPay.PublicKeyFlag && netPay.verifyAuthToken(plain, sign);
            }
            return flag;
        }

        private static string GetDateTime(DateTime dateTime)
        {
            return dateTime.ToString("yyyyMMdd");
        }

        private static string GetAmount(decimal amount)
        {
            return amount.ToString("000000000000");
        }
    }
}